
#include "gameroom.h"
#include "gameselect.h"
#include <QIcon>
#include <QPixmap>
#include <QPainter>
#include <QTimer>
#include <QDebug>
#include <QFile>
#include <QPushButton>
#include <QMessageBox>
#include <QTextEdit>
#include <QSound>
#include <QKeyEvent>


GameRoom::GameRoom(QWidget *parent) : QWidget(parent)
{
    // 初始化窗口设置
    this->setFixedSize(1000, 800);
    this->setWindowTitle("贪吃蛇游戏");
    this->setWindowIcon(QIcon(":/D:/photo/1.webp"));

    // 初始化贪吃蛇
    snakeList.push_back(QRectF(this->width() * 0.5, this->height() * 0.5, kSnakeNodeWidth, kSnakeNodeHeight));
    moveUp();
    moveUp();

    createNewFood();// 初始化食物

    timer = new QTimer(this);
    connect(timer, &QTimer::timeout, [=](){
        int count = 1;

        if (snakeList.front().intersects(foodRect)){
            createNewFood();
            ++count;

            QSound::play(":/D:/photo/1.webp");
        }

        while (count--) {
            // 处理蛇的移动
            switch (moveDirect) {
            case snakeDirect::UP:
                moveUp();
                break;
            case snakeDirect::DOWN:
                moveDown();
                break;
            case snakeDirect::LEFT:
                moveLeft();
                break;
            case snakeDirect::RIGHT:
                moveRight();
                break;
            default:
                qDebug() << "非法移动方向";
                break;
            }
        }
        // 删除最后一个节点
        snakeList.pop_back();
        update();
    });


    // 开始游戏 & 暂停游戏
    QPushButton* startBtn = new QPushButton(this);
    QPushButton* stopBtn = new QPushButton(this);

    QFont ft("楷体", 15, QFont::ExtraLight, false);

    // 设置按钮的位置
    startBtn->move(840, 150);
    stopBtn->move(840, 220);

    // 设置按钮文本
    startBtn->setText("开始");
    stopBtn->setText("暂停");

    // 设置按钮样式
    startBtn->setStyleSheet("QPushButton {"
                                "background-color: white;"// 按钮背景颜色
                                "color: #4CAF50;" // 文字颜色
                                "border: 2px solid #4CAF50;" // 边框
                                "border-radius: 8px;" // 边框圆角
                                "padding: 10px 20px;" // 内边距
                            "}");

    stopBtn->setStyleSheet("QPushButton {"
                                "background-color: white;"// 按钮背景颜色
                                "color: #4CAF50;" // 文字颜色
                                "border: 2px solid #4CAF50;" // 边框
                                "border-radius: 8px;" // 边框圆角
                                "padding: 10px 20px;" // 内边距
                            "}");

    // 设置按钮字体格式
    startBtn->setFont(ft);
    stopBtn->setFont(ft);

    connect(startBtn, &QPushButton::clicked, [=](){
        sound = new QSound(":res/Trepak.wav");
        sound->play();
        sound->setLoops(-1);// 循环播放

        isGameStart = true;
        timer->start(moveTimeout);
    });

    connect(stopBtn, &QPushButton::clicked, [=](){
        sound->stop();

        isGameStart = false;
        timer->stop();
    });



    QPushButton* Up = new QPushButton(this);
    QPushButton* Down = new QPushButton(this);
    QPushButton* Left = new QPushButton(this);
    QPushButton* Right = new QPushButton(this);

    QString buttonStyle =
                    "QPushButton {"
                    "    border: 2px solid #8f8f8f;"
                    "    border-radius: 10px;"
                    "    background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #f0f0f0, stop: 1 #bbbbbb);"
                    "    color: #000000;"
                    "}"
                    "QPushButton:hover {"
                    "    background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffffff, stop: 1 #8f8f8f);"
                    "}"
                    "QPushButton:pressed {"
                    "    background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #dadada, stop: 1 #949494);"
                    "}";

    Up->move(880, 400);
    Down->move(880, 480);
    Left->move(840, 440);
    Right->move(920, 440);

    QFont font("楷体", 15, QFont::ExtraLight, false);
    Up->setStyleSheet(buttonStyle);

    Up->setFont(font);
    Up->setText("↑");

    Down->setStyleSheet(buttonStyle);
    Down->setFont(font);
    Down->setText("↓");

    Left->setStyleSheet(buttonStyle);
    Left->setFont(font);
    Left->setText("←");

    Right->setStyleSheet(buttonStyle);
    Right->setFont(font);
    Right->setText("→");

    connect(Up, &QPushButton::clicked, [=](){
        if (moveDirect != snakeDirect::DOWN){
            moveDirect = snakeDirect::UP;
        }
    });

    connect(Down, &QPushButton::clicked, [=](){
        if (moveDirect != snakeDirect::UP){
            moveDirect = snakeDirect::DOWN;
        }
    });

    connect(Left, &QPushButton::clicked, [=](){
        if (moveDirect != snakeDirect::RIGHT){
            moveDirect = snakeDirect::LEFT;
        }
    });

    connect(Right, &QPushButton::clicked, [=](){
        if (moveDirect != snakeDirect::LEFT){
            moveDirect = snakeDirect::RIGHT;
        }
    });


    // 退出游戏按钮
    QPushButton* exitGame = new QPushButton(this);
    exitGame->setStyleSheet("QPushButton {"
                            "background-color: white;" // 按钮背景颜色
                            "color: #4CAF50;" // 文字颜色
                            "border: 2px solid #4CAF50;" // 边框
                            "border-radius: 8px;" // 边框圆角
                            "padding: 10px 20px;" // 内边距
                            "}");

    exitGame->move(840, 725);
    exitGame->setText("退出");
    exitGame->setFont(font);


    // 消息提示
    QMessageBox* messageBox = new QMessageBox(this);
    QPushButton* okbtn = new QPushButton("ok");
    QPushButton* cancelbtn = new QPushButton("cancel");

    messageBox->setWindowIcon(QIcon(":res/ico.png"));// 设置消息对话框的图标
    messageBox->setWindowTitle("退出游戏");// 设置消息对话框的标题
    messageBox->setText("确认退出游戏吗?");// 设置消息对话框内容
    messageBox->setIcon(QMessageBox::Question); //设置消息对话框类型

    messageBox->addButton(okbtn, QMessageBox::AcceptRole);//Accept Role：接受的角色
    messageBox->addButton(cancelbtn, QMessageBox::RejectRole);//Reject Role：排斥作用


    connect(exitGame, &QPushButton::clicked, [=](){
        messageBox->show();// 消息提示
        QSound::play(":res/clicked.wav");
        messageBox->exec();// 阻塞等待用户输入

        GameSelect* s = new GameSelect;

        if (messageBox->clickedButton() == okbtn){
            this->close();
            //如果点击了 Ok 按钮，那么就会跳转到游戏关卡界⾯
            s->show();
            s->setGeometry(this->geometry());
            QSound::play(":res/clicked.wav");
        }else{
            messageBox->close();
            QSound::play(":res/clicked.wav");
        }
    });
}





// 重写绘图事件，实现贪吃蛇游戏游戏背景效果
void GameRoom::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    QPixmap pix;
    pix.load(":/D:/photo/3.jpeg");
    painter.drawPixmap(0, 0, 800, 800, pix);
    painter.setRenderHint(QPainter::Antialiasing);// 设置抗锯齿

    // 蛇 = 蛇头 + 蛇身体 + 蛇尾巴
    // 渲染蛇头
    if (moveDirect == snakeDirect::UP){
        pix.load(":/D:/snake/1.png");
    }else if (moveDirect == snakeDirect::DOWN){
        pix.load(":/D:/snake/1.png");
    }else if (moveDirect == snakeDirect::LEFT){
        pix.load(":/D:/snake/1.png");
    }else {
        pix.load(":/D:/snake/1.png");
    }

    auto snakeHead = snakeList.front();
    painter.drawPixmap(snakeHead.x(), snakeHead.y(), snakeHead.width(), snakeHead.height(), pix);

    // 渲染蛇身体
    pix.load(":/D:/snake/3.png");
    for (int i = 1; i < snakeList.size() - 1; i++){
        auto node = snakeList.at(i);
        painter.drawPixmap(node.x(), node.y(), node.width(), node.height(), pix);
    }

    // 渲染蛇尾巴
    auto snakeTail = snakeList.back();
    painter.drawPixmap(snakeTail.x(), snakeTail.y(), snakeTail.width(), snakeTail.height(), pix);

    // 渲染食物
    pix.load(":/D:/snake/5.png");
    painter.drawPixmap(foodRect.x(), foodRect.y(), foodRect.width(), foodRect.height(), pix);

    // 渲染右边区域
    pix.load(":/D:/snake/7png.png");
    painter.drawPixmap(800, 0, 200, 1000, pix);

    // 渲染分数
    pix.load(":res/sorce_bg.png");
    painter.drawPixmap(this->width() * 0.85, this->height() * 0.02, 100, 50, pix);
    QPen pen;
    pen.setColor(Qt::black);
    painter.setPen(pen);
    QFont font("楷体", 15, QFont::ExtraLight, false);
    painter.setFont(font);
    painter.drawText(this->width() * 0.9, this->height() * 0.075, QString("%1").arg(snakeList.size()));

    // 往文件中写入得分
    int c = snakeList.size();
    QFile file(":/D:/snake_2/1.txt");
    if (file.open(QIODevice::WriteOnly | QIODevice::Text)){
        QTextStream out(&file);
        int num = c;
        out << num;// 将int类型数据写入文件
        file.close();
    }

    // 如果失败，渲染 GAME OVER

    if (checkFail()){
        pen.setColor(Qt::red);
        painter.setPen(pen);
        QFont font("微软雅黑", 40, QFont::ExtraLight, false);
        painter.setFont(font);
        painter.drawText(this->width() * 0.1, this->height() * 0.5, QString("GAME OVER"));
        timer->stop();

        QSound::play(":res/gameover.wav");
        sound->stop();
    }
}



// 创建食物
void GameRoom::createNewFood()
{
    foodRect = QRectF(
                qrand()%(this->width()/kSnakeNodeWidth) * kSnakeNodeWidth,
                           qrand()%(this->height()/kSnakeNodeHeight) * kSnakeNodeHeight,
                           kSnakeNodeWidth,
                           kSnakeNodeHeight);



}



// 实现向上移动
void GameRoom::moveUp()
{
    QPointF leftTop;// 左上角坐标
    QPointF rightBottom;// 右下角坐标

    auto snakeNode = snakeList.front();

    int headX = snakeNode.x();
    int headY = snakeNode.y();

    // 如果上面剩余的空间不够放入⼀个新的节点, 相当于到墙边了, 要处理穿墙逻辑
    if (headY < 0){
        leftTop = QPointF(headX, this->height() - kSnakeNodeHeight);
    }else {
        leftTop = QPointF(headX, headY - kSnakeNodeHeight);
    }

    rightBottom = leftTop + QPointF(kSnakeNodeWidth, kSnakeNodeHeight);
    snakeList.push_front(QRectF(leftTop, rightBottom));
}



// 实现向下移动
void GameRoom::moveDown()
{
    QPointF leftTop;// 左上角坐标
    QPointF rightBottom;// 右下角坐标

    auto snakeNode = snakeList.front();

    int headX = snakeNode.x();
    int headY = snakeNode.y();

    // 如果下面剩余的空间不够放入⼀个新的节点, 相当于到墙边了, 要处理穿墙逻辑
    if (headY > this->height()){
        leftTop = QPointF(headX, 0);
    }else {
        leftTop = snakeNode.bottomLeft();// 返回矩形左下角的坐标
    }

    rightBottom = leftTop + QPointF(kSnakeNodeWidth, kSnakeNodeHeight);
    snakeList.push_front(QRectF(leftTop, rightBottom));
}



// 实现向左移动
void GameRoom::moveLeft()
{
    QPointF leftTop;// 左上角坐标
    QPointF rightBottom;// 右下角坐标

    auto snakeNode = snakeList.front();

    int headX = snakeNode.x();
    int headY = snakeNode.y();

    // 如果左面剩余的空间不够放入⼀个新的节点, 相当于到墙边了, 要处理穿墙逻辑
    if (headX < 0){
        leftTop = QPointF(800 - kSnakeNodeWidth, headY);
    }else {
        leftTop = QPointF(headX - kSnakeNodeWidth, headY);
    }

    rightBottom = leftTop + QPointF(kSnakeNodeWidth, kSnakeNodeHeight);
    snakeList.push_front(QRectF(leftTop, rightBottom));
}



// 实现向右移动
void GameRoom::moveRight()
{
    QPointF leftTop;// 左上角坐标
    QPointF rightBottom;// 右下角坐标

    auto snakeNode = snakeList.front();

    int headX = snakeNode.x();
    int headY = snakeNode.y();

    // 如果右面剩余的空间不够放入⼀个新的节点, 相当于到墙边了, 要处理穿墙逻辑
    if (headX > 760){
        leftTop = QPointF(0, headY);
    }else {
        leftTop = snakeNode.topRight();// 返回矩形右上角的坐标
    }

    rightBottom = leftTop + QPointF(kSnakeNodeWidth, kSnakeNodeHeight);
    snakeList.push_front(QRectF(leftTop, rightBottom));

    if(headX<0)
    {
        return;
    }

}

// 判断游戏是否结束
bool GameRoom::checkFail()
{

    // 判断头尾是否出现相交
    for (int i = 0; i < snakeList.size(); i++)
    {
        for (int j = i + 1; j < snakeList.size(); j++)
        {
            if (snakeList.at(i) == snakeList.at(j))
            {
                return true;
            }
        }
    }
    return false;

}


